package com.cysyz.web.modules.base.inputvalidation.aspect;

import com.cysyz.mylib.domain.BaseEntity;
import com.cysyz.web.modules.base.exceptionhandle.exception.AjaxOutLayerInputRuntimeException;
import com.cysyz.web.modules.base.exceptionhandle.exception.OutLayerInputRuntimeException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.lang.reflect.Method;
import java.util.Set;

@Aspect
public class ControllerInputValidateAspect {
    //ValidatorFactory factory = Validation.byProvider(MyHibernateValidator.class).configure().buildValidatorFactory();
    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private void pointCutMethod() {
    }

    //声明前置通知  
    //@Before("pointCutMethod()")
    public void doBefore(JoinPoint jp) {


    }  
  
    //声明后置通知  
    //@AfterReturning(pointcut = "pointCutMethod()", returning = "result")
    public void doAfterReturning(String result) {  
        System.out.println("后置通知");  
        System.out.println("---" + result + "---");  
    }  
  
    //声明例外通知  
    //@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {  
        System.out.println("例外通知");  
        System.out.println(e.getMessage());  
    }  
  
    //声明最终通知  
    //@After("pointCutMethod()")
    public void doAfter() {  
        System.out.println("最终通知");  
    }  
  
    //声明环绕通知  
    /*@Around("pointCutMethod()")*/
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (args != null) {
            /* 根据@ValidateConfig中includex即excludes的值来有选择性地对属性进行校验的功能，暂时不提供。20150204
            if (method.isAnnotationPresent(ValidateConfig.class)) {
                ValidateConfig validateConfig = method.getAnnotation(ValidateConfig.class);
                MyFilter myFilter = new SimpleMyFilter(Arrays.asList(validateConfig.includes()), Arrays.asList(validateConfig.exclude()));

            }*/

            for (Object arg : args) {
                if (arg instanceof BaseEntity) {
                    Validator validator = factory.getValidator();
                    Set<ConstraintViolation<Object>> constraintViolations = validator.validate(arg);

                    if (!constraintViolations.isEmpty()) {
                        StringBuilder messageBuilder = new StringBuilder();
                        for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
                            messageBuilder.append(constraintViolation.getMessage());
                            messageBuilder.append(":");
                        }
                        if (method.isAnnotationPresent(ResponseBody.class)) {
                            throw new AjaxOutLayerInputRuntimeException(messageBuilder.toString());
                        } else {
                            throw new OutLayerInputRuntimeException(messageBuilder.toString());
                        }
                    }
                }
            }
        }

        Object o = pjp.proceed();
        return o;  
    }  
} 